﻿namespace Resharper.Abstractions.Solutions
{
  using System;
  using JetBrains.Annotations;
  using JetBrains.ReSharper.Psi;
  using JetBrains.ReSharper.Psi.CodeStyle;
  using JetBrains.ReSharper.Psi.Impl.CodeStyle.Obsolete;
  using JetBrains.ReSharper.Psi.Naming.Settings;
  using JetBrains.ReSharper.Psi.Tree;
  using Resharper.Abstractions.Actions;

  /// <summary>Defines the <see cref="Naming"/> class.</summary>
  public class Naming
  {
    #region Constants and Fields

    /// <summary>The solution field.</summary>
    private readonly Solution solution;

    #endregion

    #region Constructors and Destructors

    /// <summary>Initializes a new instance of the <see cref="Naming"/> class.</summary>
    /// <param name="solution">The solution.</param>
    public Naming([NotNull] Solution solution)
    {
      if (solution == null)
      {
        throw new ArgumentNullException("solution");
      }

      this.solution = solution;
    }

    #endregion

    #region Public Methods

    /// <summary>Gets the name of the canonical.</summary>
    /// <param name="context">The context.</param>
    /// <param name="language">The language.</param>
    /// <param name="name">The name.</param>
    /// <returns>Returns the canonical name.</returns>
    [NotNull]
    public string GetCanonicalName([NotNull] ExecuteContext context, [NotNull] Language language, [NotNull] string name)
    {
      if (context == null)
      {
        throw new ArgumentNullException("context");
      }

      if (language == null)
      {
        throw new ArgumentNullException("language");
      }

      if (name == null)
      {
        throw new ArgumentNullException("name");
      }

      var selectedElement = context.InternalProvider.GetSelectedElement<ITreeNode>(false, true);
      if (selectedElement == null)
      {
        return name;
      }

      var sourceFile = selectedElement.GetSourceFile();
      if (sourceFile == null)
      {
        return name;
      }

      var namingManager = this.solution.InternalSolution.GetPsiServices().Naming;

      var rule = namingManager.Policy.GetDefaultRule(NamedElementKinds.Constants, selectedElement.Language, sourceFile);

      var n = namingManager.Parsing.Parse(name, rule, language.InternalLanguage, sourceFile);

      return n.GetCanonicalName() ?? name;
    }

    #endregion
  }
}